﻿//****************************************************************************
// Copyright (c) Microsoft Corporation. All rights reserved.
//****************************************************************************
using System;
using System.Reflection;
using System.Collections.Generic;
using System.Text;
using Microsoft.FxCop.Sdk;

namespace Microsoft.FxCop.Rules.ASP.Security
{
    abstract class BasePageIntrospectionRule : BaseIntrospectionRule
    {
        #region *** Fields ***
        private bool m_skipAnalysis = false;
        #endregion

        #region *** Properties ***
        public override TargetVisibilities TargetVisibility
        {
            get{ return TargetVisibilities.ExternallyVisible | TargetVisibilities.NotExternallyVisible | TargetVisibilities.Overridable; }
        }
        #endregion

        #region *** Constructor ***
        protected BasePageIntrospectionRule(string name, string resourceName, Assembly resourceAssembly)
            : base(name, resourceName, resourceAssembly)
        {
        }

        protected BasePageIntrospectionRule(string name)
            : this(name, "Microsoft.FxCop.Rules.ASP.Security.ASPSecurityRules", typeof(BasePageIntrospectionRule).Assembly)
        {
        }
        #endregion

        #region *** Methods ***

        #region *** BaseIntrospectionRule ***

        public override void BeforeAnalysis()
        {
            // If the assemblies analyzed are not referencing System.web.dll the call will return null even if the
            // assembly is in the GAC.
            m_skipAnalysis = (FrameworkTypes.Page == null);
        }

        public override ProblemCollection Check(TypeNode type)
        {
            Method method;

            if (m_skipAnalysis || (type == null) || !(type.IsDerivedFrom(FrameworkTypes.Page)))
                return null;

            if (!ShouldAnalyzeType(type))
                return null;

            foreach (Member member in type.Members)
            {
                if ((method = member as Method) != null)
                {
                    if (PageHelper.IsPageLoadMethod(method))
                        CheckPageLoad(method);
                    else if (PageHelper.IsPageInitMethod(method))
                        CheckPageInit(method);
                    else if (PageHelper.IsOnInitMethod(method))
                        CheckPageInit(method);
                    else if (PageHelper.IsBuildControlTreeMethod(method))
                        CheckBuildControlTree(method);
                    else if (PageHelper.IsFrameworkInitializeMethod(method))
                        CheckFrameworkInitialized(method);
                    else
                        CheckPageMethod(method);
                }
            }

            return base.Problems;
        }

        #endregion


        #region *** Abstract ***

        protected virtual void CheckPageMethod(Method method)
        {
            return;
        }
        protected virtual void CheckBuildControlTree(Method buildTreeMethod)
        {
            return;
        }

        protected virtual void CheckPageInit(Method pageInit)
        {
            return;
        }

        protected virtual void CheckPageLoad(Method pageLoad)
        {
            return;
        }

        protected virtual void CheckFrameworkInitialized(Method frameworkInit)
        {
            return;
        }
        #endregion

        protected void ReportProblem()
        {
            ReportProblem(null);
        }

        protected void ReportProblem(string issueData)
        {
            Problem problem;

            if( string.IsNullOrEmpty(issueData) )
                problem = new Problem( base.GetResolution() );
            else
                problem = new Problem(base.GetResolution(new string[] { issueData }));

            base.Problems.Add(problem);
        }

        protected virtual bool ShouldAnalyzeType(TypeNode type)
        {
            // We need to check to see if the type inherit from the MVC ViewPage which doesn't use Viewstate
            // Since MVC ViewPage.
            if (Microsoft.FxCop.Rules.ASP.MVC.Security.MVCHelper.IsMVCViewPage(type))
                return false;

            return type.IsDerivedFrom(FrameworkTypes.Page);
        }

        #endregion
    }
}
